<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
  <TITLE> New Document </TITLE>
  <META NAME="Generator" CONTENT="EditPlus">
  <META NAME="Author" CONTENT="">
  <META NAME="Keywords" CONTENT="">
  <META NAME="Description" CONTENT="">
  <style>.page-meteor-canvas {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background: -webkit-gradient(linear, left top, left bottom, from(#000000), to(#1e004e));
  background: linear-gradient(to bottom, #000000, #1e004e);
}

.page-meteor-canvas:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  opacity: 0.1;
  background: url("http://static.dar-studio.com/codepen/images/night-sky.jpg") center bottom;
  background-size: cover;
}

.page-meteor-canvas canvas {
  position: absolute;
  display: block;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

.page-meteor-canvas #canvas {
  mix-blend-mode: multiply;
}

.page-meteor-canvas #buffer {
  -webkit-filter: blur(6px) brightness(10) contrast(1.25);
  filter: blur(6px) brightness(10) contrast(1.25);
  mix-blend-mode: screen;
}
</style>
 </HEAD>

 <BODY><div class="page page-meteor-canvas">
	<canvas id="buffer"></canvas>
	<canvas id="canvas"></canvas>
</div>
  <script>"use strict";

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function Meteor(options) {
	var _this = this;

	options = options || {};
	this.main = options.main || {};
	this.ctx = options.ctx;
	this.vfx = options.vfx;
	this.position = options.position || {
		x: Math.random() * this.main.width + this.main.width * 0.25,
		y: Math.random() * -this.main.height * 0.25
	};
	this.rotation = options.rotation || Math.random() * 2 * Math.PI;
	this.velocity = options.velocity || {
		phi: Math.random() * 0.4 - 0.2 + Math.PI * 0.75,
		length: Math.random() * 5 + 1,
		rotate: Math.random() * 0.1 - 0.05
	};
	this.gravity = options.gravity || { phi: Math.PI * 0.5, length: 0.98 };
	this.edge = options.edge || ~~(Math.random() * this.velocity.length + this.velocity.length * 2 + 2);
	this.color = options.color || ["#300", "#610", "#fd2", "#f62"];
	this.timescale = options.timescale || 0.5;
	this.ground = options.ground || this.main.height;
	this.accelerate = options.accelerate || {
		phi: {
			change: Math.random() * 0.015 - 0.0075,
			min: Math.PI * 0.6,
			max: Math.PI * 0.9
		},
		friction: 1.005
	};
	this.points = [].concat(_toConsumableArray(new Array(this.edge))).map(function (e, i) {
		var phi = i / _this.edge * 2 * Math.PI;
		return {
			phi: phi + Math.random() * 0.4 - 0.2,
			length: Math.random() * _this.velocity.length * 2 + _this.velocity.length * 4
		};
	});

	this.update = function (i) {
		this.rotation += this.velocity.rotate * this.timescale;
		this.position.x += Math.cos(this.velocity.phi) * this.velocity.length * this.timescale;
		this.position.y += Math.sin(this.velocity.phi) * this.velocity.length * this.timescale;
		this.position.x += Math.cos(this.gravity.phi) * this.gravity.length * this.timescale;
		this.position.y += Math.sin(this.gravity.phi) * this.gravity.length * this.timescale;
		this.velocity.phi += this.accelerate.phi.change * this.timescale;
		(this.velocity.phi > this.accelerate.phi.max || this.velocity.phi < this.accelerate.phi.min) && (this.accelerate.phi.change = -this.accelerate.phi.change);
		this.velocity.length *= this.accelerate.friction;
		if (this.position.y > this.ground) {
			var ctx = this.vfx;
			var position = this.position;
			var range = this.edge;
			var main = this.main;
			[].concat(_toConsumableArray(new Array(this.edge))).map(function () {
				return main.makeRock({
					position: { x: position.x, y: position.y },
					base: range
				}) || LightFlare(ctx, position.x + Math.random() * 10 * range - 5 * range, position.y + Math.random() * 6 * range - 3 * range, range * Math.random() * 30 + 30);
			});
			this.main.meteors.splice(i, 1);
			this.main.makeMeteor();
		}
	};

	this.render = function () {
		var _this2 = this;

		var ctx = this.ctx;
		ctx.strokeStyle = this.color[0];
		ctx.fillStyle = this.color[1];
		ctx.moveTo(this.position.x, this.position.y);
		ctx.beginPath();
		this.points.forEach(function (p) {
			var x = Math.cos(p.phi + _this2.rotation) * p.length + _this2.position.x;
			var y = Math.sin(p.phi + _this2.rotation) * p.length + _this2.position.y;
			ctx.lineTo(x, y);
		});
		ctx.closePath();
		ctx.stroke();
		ctx.fill();
		//
		var vfx = this.vfx;
		vfx.globalAlpha = Math.random();
		vfx.fillStyle = this.color[2 + ~~(Math.random() + 0.6)];
		vfx.moveTo(this.position.x, this.position.y);
		vfx.beginPath();
		this.points.forEach(function (p) {
			var x = Math.cos(p.phi + _this2.rotation * Math.random() * 0.2 - 0.1) * p.length + Math.random() + _this2.position.x;
			var y = Math.sin(p.phi + _this2.rotation * Math.random() * 0.2 - 0.1) * p.length + Math.random() + _this2.position.y;
			vfx.lineTo(x, y);
		});
		vfx.closePath();
		vfx.fill();
	};
}

function Rock(options) {
	var _this3 = this;

	options = options || {};
	this.main = options.main || {};
	this.base = options.base || 2;
	this.ctx = options.ctx;
	this.vfx = options.vfx;
	this.position = options.position || {
		x: Math.random() * this.main.width,
		y: Math.random() * this.main.height
	};
	this.rotation = options.rotation || Math.random() * 2 * Math.PI;
	this.velocity = options.velocity || {
		phi: Math.random() * Math.PI * 0.5 + Math.PI * 1.25,
		length: Math.random() * 1.5 * this.base + 15,
		rotate: Math.random() * 0.2 - 0.1
	};
	this.gravity = options.gravity || { phi: Math.PI * 0.5, length: 5 };
	this.edge = options.edge || ~~(Math.random() * this.velocity.length + this.velocity.length * 2 + 5);
	this.color = options.color || ["#300", "#510", "#fd2", "#f62"];
	this.timescale = options.timescale || 1.5;
	this.lifespan = options.lifespan || ~~(Math.random() * 30 + 10);
	this.friction = 0.94;
	this.points = [].concat(_toConsumableArray(new Array(this.edge))).map(function (e, i) {
		var phi = i / _this3.edge * 2 * Math.PI;
		return {
			phi: phi + Math.random() * 0.4 - 0.2,
			length: Math.random() * _this3.velocity.length * 0.1 + _this3.velocity.length * 0.2
		};
	});

	this.update = function (i) {
		if (this.lifespan-- <= 0) {
			this.main.meteors.splice(i, 1);
			return;
		}
		this.rotation += this.velocity.rotate * this.timescale;
		this.position.x += Math.cos(this.velocity.phi) * this.velocity.length * this.timescale;
		this.position.y += Math.sin(this.velocity.phi) * this.velocity.length * this.timescale;
		this.position.x += Math.cos(this.gravity.phi) * this.gravity.length * this.timescale;
		this.position.y += Math.sin(this.gravity.phi) * this.gravity.length * this.timescale;
		this.velocity.length *= this.friction;
	};

	this.render = function () {
		var _this4 = this;

		var ctx = this.ctx;
		ctx.globalAlpha = Math.random();
		ctx.strokeStyle = this.color[0];
		ctx.fillStyle = this.color[1];
		ctx.moveTo(this.position.x, this.position.y);
		ctx.beginPath();
		this.points.forEach(function (p) {
			var x = Math.cos(p.phi + _this4.rotation) * p.length + _this4.position.x;
			var y = Math.sin(p.phi + _this4.rotation) * p.length + _this4.position.y;
			ctx.lineTo(x, y);
		});
		ctx.closePath();
		ctx.stroke();
		ctx.fill();
		ctx.globalAlpha = 1;
		//
		var vfx = this.vfx;
		vfx.globalAlpha = Math.random();
		vfx.fillStyle = this.color[2 + ~~(Math.random() + 0.6)];
		vfx.moveTo(this.position.x, this.position.y);
		vfx.beginPath();
		this.points.forEach(function (p) {
			var x = Math.cos(p.phi + _this4.rotation * Math.random() * 0.2 - 0.1) * p.length + Math.random() + _this4.position.x;
			var y = Math.sin(p.phi + _this4.rotation * Math.random() * 0.2 - 0.1) * p.length + Math.random() + _this4.position.y;
			vfx.lineTo(x, y);
		});
		vfx.closePath();
		vfx.fill();
	};
}

function LightFlare(ctx, x, y, range) {
	range = range || 100;
	var strength = Math.random() * range + range;
	var light = ctx.createRadialGradient(x, y, 0, x, y, strength);
	light.addColorStop(0, "rgba(250, 200, 50, 0.4)");
	light.addColorStop(0.1, "rgba(250, 200, 50, 0.3)");
	light.addColorStop(0.4, "rgba(250, 200, 50, 0.2)");
	light.addColorStop(0.65, "rgba(250, 200, 50, 0.1)");
	light.addColorStop(0.8, "rgba(250, 200, 50, 0.05)");
	light.addColorStop(1, "rgba(250, 200, 50, 0)");
	ctx.globalAlpha = 1;
	ctx.beginPath();
	ctx.fillStyle = light;
	ctx.arc(x, y, strength, 0, Math.PI * 2);
	ctx.fill();
	ctx.closePath();
}

function Ground(options) {
	var _this5 = this;

	options = options || {};
	this.main = options.main || {};
	this.ctx = options.ctx;
	this.edge = options.edge || ~~(Math.random() * 10 + 40);
	this.color = options.color || ["#222", "#1e004e"];
	this.height = options.height || this.main.height * 0.16;
	this.points = [].concat(_toConsumableArray(new Array(this.edge))).map(function (e, i) {
		var rand = 1 / _this5.edge * _this5.main.width;
		return {
			x: i / _this5.edge * _this5.main.width + Math.random() * rand - rand * 0.5,
			y: _this5.main.height - _this5.height + Math.random() * _this5.height * 0.1
		};
	});

	this.update = function () {
		return;
	};

	this.render = function () {
		var ctx = this.ctx;
		ctx.strokeStyle = this.color[0];
		ctx.fillStyle = this.color[1];
		ctx.beginPath();
		ctx.moveTo(-this.height, this.main.height);
		this.points.forEach(function (p) {
			return ctx.lineTo(p.x, p.y);
		});
		ctx.lineTo(this.main.width + this.height, this.main.height);
		ctx.closePath();
		ctx.stroke();
		ctx.fill();
	};
}

var main = {
	canvas: document.getElementById("canvas"),
	buffer: document.getElementById("buffer"),
	ctx: null,
	vfx: null,
	ground: null,
	meteors: [],
	count: 8,
	width: window.innerWidth,
	height: window.innerHeight,
	init: function init() {
		var _this6 = this;

		this.registerEvents();
		this.ctx = this.canvas.getContext("2d");
		this.vfx = this.buffer.getContext("2d");
		this.vfx.globalCompositeOperation = "screen";
		//
		this.resize();
		//
		this.ground = new Ground({
			ctx: this.ctx,
			main: this
		});
		[].concat(_toConsumableArray(new Array(this.count))).map(function () {
			return _this6.makeMeteor();
		});
	},

	makeMeteor: function makeMeteor() {
		this.meteors.push(new Meteor({
			ctx: this.ctx,
			vfx: this.vfx,
			ground: this.height - this.ground.height * 0.8,
			main: this
		}));
	},
	makeRock: function makeRock(options) {
		options = options || {};
		this.meteors.push(new Rock({
			ctx: this.ctx,
			vfx: this.vfx,
			position: options.position,
			base: options.base,
			main: this
		}));
	},


	update: function update() {
		this.meteors.forEach(function (m, i) {
			return m.update(i);
		});
		this.ground.update();
	},

	render: function render() {
		this.ctx.clearRect(0, 0, this.width, this.height);
		this.meteors.forEach(function (m) {
			return m.render();
		});
		this.ground.render();
		//
		this.vfx.fillStyle = "#000000";
		this.vfx.globalAlpha = Math.random() * 0.12;
		this.vfx.fillRect(0, 0, this.width, this.height);
	},

	resize: function resize() {
		this.width = window.innerWidth * 1.5;
		this.height = window.innerHeight * 1.5;
		this.canvas.width = this.width;
		this.canvas.height = this.height;
		this.buffer.width = this.width;
		this.buffer.height = this.height;
	},

	registerEvents: function registerEvents() {
		var _this7 = this;

		window.addEventListener("resize", function () {
			_this7.resize();
		}, false);
	}
};

main.init();
(function loop() {
	main.update();
	main.render();
	window.requestAnimationFrame(loop);
})();</script>
 </BODY>
</HTML>
